package stdx;

import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

public class TaskQueue{
	public static class WorkItem implements Runnable{
		long etime = 0;
		Runnable item = null;

		public WorkItem(){
		}
		public WorkItem(Runnable item){
			this(item, 0);
		}
		public WorkItem(Runnable item, long delay){
			this.setDelay(delay);
			this.item = item;
		}

		public void run(){
			if (item != null) item.run();
		}
		public boolean runnable(){
			if (etime <= 0 || System.currentTimeMillis() > etime) return true;

			Utils.Sleep(1);

			return false;
		}
		public void setDelay(long delay){
			etime = delay > 0 ? System.currentTimeMillis() + delay : 0;
		}
	}

	BlockingQueue<Runnable> queue = null;
	static TaskQueue taskqueue = new TaskQueue();

	public void start(int threads){
		if (queue == null) queue = new LinkedBlockingQueue<Runnable>();

		while (threads-- > 0){
			new Thread(){
				public void run(){
					while (true){
						try{
							Runnable item = queue.take();

							if (item instanceof WorkItem){
								if (((WorkItem)(item)).runnable()){
									item.run();
								}
								else{
									queue.add(item);
								}
							}
							else {
								item.run();
							}
						}
						catch(Exception e){
							e.printStackTrace();

							Utils.Sleep(10);
						}
					}
				}
			}.start();
		}
	}
	public boolean push(WorkItem task){
		if (task == null) return false;

		if (queue == null){
			synchronized(this){
				if (queue == null) start(4);
			}
		}

		try{
			queue.put(task);

			return true;
		}
		catch(Exception e){
			return false;
		}
	}
	public boolean push(Runnable task){
		return push(task, 0);
	}
	public boolean push(Runnable task, long delay){
		if (task == null) return false;

		if (queue == null){
			synchronized(this){
				if (queue == null) start(4);
			}
		}

		try{
			if (delay > 0) task = new WorkItem(task, delay);

			queue.put(task);

			return true;
		}
		catch(Exception e){
			return false;
		}
	}
	public static TaskQueue Instance(){
		return taskqueue;
	}
}
